package com.coolw.file.util;

import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLConverter;
import fr.opensagres.poi.xwpf.converter.xhtml.XHTMLOptions;
import lombok.Cleanup;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.lang.Assert;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * word转html工具类
 * <p>
 * https://www.cnblogs.com/ismallboy/p/12584761.html
 *
 * @author coolw
 * @date 2022/10/14 14:35
 */
public class WordToHtmlUtil {

    public static String wordToHtml(String fullFileName, InputStream input) throws Exception {
        Assert.notBlank(fullFileName, "文件名不能为空");
        // 文件后缀名
        String suffix = fullFileName.substring(fullFileName.lastIndexOf("."));
        if (!".doc".equals(suffix) && !".docx".equals(suffix)) {
            throw new RuntimeException("不支持的文件格式:" + suffix);
        }
        return Objects.equals(".docx", suffix) ? word2007ToHtml(input) : word2003ToHtml(input);
    }

    private static String word2007ToHtml(InputStream input) throws IOException {
        XWPFDocument document = new XWPFDocument(input);
        // 数据填充
        //fillData(document);
        // 解析XHTML配置 (这里设置IURIResolver来设置图片存放的目录)
        XHTMLOptions options = XHTMLOptions.create();
        /*Map<String, String> imgMap = new HashMap<>();
        options.setExtractor(new IImageExtractor() {
            @Override
            public void extract(String imagePath, byte[] imageData) throws IOException {
                //获取图片数据并且上传
                String fileName = AliOssUtil.generateImageFileName() + imagePath.substring(imagePath.lastIndexOf("."));
                String imgUrl = uploadFileUtil.uploadFile(imageData, bucket, directory, fileName, visitPoint);
                imgMap.put(imagePath, imgUrl);
            }
        });
        // html中图片的路径 相对路径
        options.URIResolver(new IURIResolver() {
            @Override
            public String resolve(String uri) {
                //设置图片路径
                return imgMap.get(uri);
            }
        });*/

        options.setIgnoreStylesIfUnused(false);
        options.setFragment(true);
        // 将XWPFDocument转换成 XHTML
        @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
        XHTMLConverter.getInstance().convert(document, baos, options);
        return baos.toString();
    }

    private static String word2003ToHtml(InputStream input)
            throws IOException, TransformerException, ParserConfigurationException {
        HWPFDocument wordDocument = new HWPFDocument(input);
        WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
                DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument());
        /*wordToHtmlConverter.setPicturesManager(new PicturesManager() {
            @Override
            public String savePicture(byte[] content, PictureType pictureType, String suggestedName, float widthInches,
                                      float heightInches) {
                String fileName = AliOssUtil.generateImageFileName() + suggestedName.substring(suggestedName.lastIndexOf("."));
                return uploadFileUtil.uploadFile(content, bucket, directory, fileName, visitPoint);
            }
        });*/

        // 解析word文档
        wordToHtmlConverter.processDocument(wordDocument);
        Document htmlDocument = wordToHtmlConverter.getDocument();
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            OutputStream outStream = new BufferedOutputStream(baos);
            DOMSource domSource = new DOMSource(htmlDocument);
            StreamResult streamResult = new StreamResult(outStream);
            TransformerFactory factory = TransformerFactory.newInstance();
            Transformer serializer = factory.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
            serializer.setOutputProperty(OutputKeys.INDENT, "yes");
            serializer.setOutputProperty(OutputKeys.METHOD, "html");
            serializer.transform(domSource, streamResult);
            return baos.toString();
        }
    }

    private static void fillData(XWPFDocument document) {
        Map<String, String> fileDataMap = new HashMap<>();
        fileDataMap.put("## fieldName ##", "乐享借");
        fileDataMap.put("## fieldName ##", DateUtil.formatNow());

        // 获取文档中的所有段落
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        // 遍历段落，查找包含指定字段名的段落
        for (XWPFParagraph paragraph : paragraphs) {
            // 获取段落中的所有运行对象
            List<XWPFRun> runs = paragraph.getRuns();

            // 遍历运行对象，查找包含指定字段名的文本
            for (XWPFRun run : runs) {
                for (Map.Entry<String, String> entry : fileDataMap.entrySet()) {
                    String text = run.getText(0);
                    if (text != null && text.contains(entry.getKey())) {
                        // 替换指定字段名的文本为填充的数据
                        run.setText(text.replace(entry.getKey(), entry.getValue()), 0);
                    }
                }
            }
        }
    }
}
